package com.demo2do.boyle.client.web.resolver;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.demo2do.boyle.client.Constant;
import com.demo2do.boyle.client.handler.CookieHandler;
import com.demo2do.boyle.client.handler.OpenIdAuthHandler;
import com.demo2do.boyle.common.entity.customer.Customer;
import com.demo2do.core.web.resolver.Secure;

/**
 * @author Wilson
 */
public class SecurityArgumentResolver implements HandlerMethodArgumentResolver {

	private static final Log logger = LogFactory.getLog(SecurityArgumentResolver.class);

	@Autowired
	private CookieHandler cookieHandler;

	@Autowired
	private OpenIdAuthHandler openIdAuthHandler;
	
	/* (non-Javadoc)
	 * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
	 */
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.hasParameterAnnotation(Secure.class);
	}

	/* (non-Javadoc)
	 * @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
	 */
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {


	    String openId = cookieHandler.getCookie(Constant.COOKIE_OPEN_ID, ((ServletWebRequest)webRequest).getRequest());

	    Customer customer = openIdAuthHandler.authenticate(openId);

		if (customer != null) {

			Secure secure = parameter.getParameterAnnotation(Secure.class);

			// returns principal when there is no property in Secure annotation
			if (StringUtils.isEmpty(secure.property())) {
				
		        if(parameter.getParameterType().isAssignableFrom(Customer.class)) {
		        	return customer;
		        }
				
			} else {
				
				// extract property using BeanWrapperImpl
				
				try {
					BeanWrapperImpl wrapper = new BeanWrapperImpl(customer);
					return wrapper.getPropertyValue(secure.property());
				} catch (BeansException e) {
					logger.error("Error when extracting property[" + secure.property() + "] from Security Object[" + customer + "]");
					e.printStackTrace();
				}
				
			}

		}
		
		return null;
	}
}
